<template>
  <div
    class="t-chat"
    :style="heightStyleName"
    @keyup.enter="handleSend"
  >
    <div class="web__logo">
      <img
        :src="config.img"
        class="web__logo-img"
        alt=""
      />
      <div class="web__logo-info">
        <p class="web__logo-name">{{ config.name }}</p>
        <p class="web__logo-dept">{{ config.dept }}</p>
      </div>
      <slot name="header"></slot>
    </div>
    <div class="web__content">
      <div :style="widthStyleName">
        <div
          class="web__main"
          ref="main"
        >
          <div
            class="web__main-item"
            v-for="(item, index) in list"
            :key="index"
            :class="{ 'web__main-item--mine': item.mine }"
          >
            <div class="web__main-user">
              <img :src="item.img" />
              <cite>
                {{ item.name }}
                <i>{{ item.date }}</i>
              </cite>
            </div>
            <div class="web__main-text">
              <div class="web__main-arrow"></div>
              <span
                v-if="!item.msgType || item.msgType !== 'form'"
                v-html="handleDetail(item.text.text)"
                ref="content"
              ></span>
              <div v-else>
                <el-button
                  size="small"
                  type="primary"
                  @click="$emit('useForm', item.fields)"
                >
                  使用
                </el-button>
                <form-preview :fields="item.fields" />
              </div>
              <ul
                class="web__main-list"
                v-if="!validatenull(item.text.list)"
              >
                <li
                  @click="handleItemMsg(citem)"
                  v-for="(citem, cindex) in item.text.list"
                  :key="cindex"
                >
                  {{ citem.text }}
                </li>
              </ul>
            </div>
          </div>
        </div>
        <div
          class="web__footer"
          :style="widthStyleName"
        >
          <div class="web__tools">
            <el-icon
              v-if="tools.img"
              @click="handleUpload('img')"
            >
              <ele-Picture />
            </el-icon>
            <el-icon
              v-if="tools.video"
              @click="handleUpload('video')"
            >
              <ele-VideoCamera />
            </el-icon>
            <el-icon
              v-if="tools.file"
              @click="handleUpload('file')"
            >
              <ele-FolderOpened />
            </el-icon>
            <slot name="menu"></slot>
          </div>
          <div class="web__msg">
            <textarea
              v-model="msg"
              rows="2"
              :placeholder="placeholder"
              class="web__msg-input"
            ></textarea>
            <div class="web__msg-menu">
              <el-button
                split-button
                class="web__msg-submit"
                type="primary"
                :size="size"
                @click="handleSend"
                trigger="click"
              >
                发送
              </el-button>
            </div>
          </div>
        </div>
      </div>
      <slot></slot>
    </div>
  </div>
</template>

<script>
import dayjs from "dayjs";
import FormPreview from "./FormPreview.vue";
import { defineComponent } from "vue";
export default defineComponent({
  name: "Chat",
  components: {
    FormPreview
  },
  emits: ["update:modelValue", "submit", "change", "keyadd", "keysend", "useForm"],
  data() {
    return {
      upload: {
        box: false,
        src: "",
        type: "",
        title: ""
      },
      visible: false,
      imgSrc: "",
      videoSrc: "",
      audioSrc: "",
      keys: "",
      show: false
    };
  },
  props: {
    size: {
      type: String,
      default: "default"
    },
    beforeOpen: Function,
    tools: {
      type: Object,
      default: () => {
        return {
          img: false,
          video: false,
          file: false
        };
      }
    },
    placeholder: {
      type: String,
      default: "请输入..."
    },
    width: {
      type: [String, Number],
      default: 320
    },
    height: {
      type: [String, Number],
      default: 520
    },
    modelValue: {
      type: String
    },
    audio: {
      type: Array,
      default: () => {
        return [
          "https://www.helloweba.net/demo/notifysound/notify.ogg",
          "https://www.helloweba.net/demo/notifysound/notify.mp3",
          "https://www.helloweba.net/demo/notifysound/notify.wav"
        ];
      }
    },
    config: {
      type: Object,
      default: () => {
        return {};
      }
    },
    showKeyList: {
      type: Boolean,
      default: true
    },
    keylist: {
      type: Array,
      default: () => {
        return [];
      }
    },
    list: {
      type: Array,
      default: () => {
        return [];
      }
    }
  },
  computed: {
    msg: {
      get() {
        return this.modelValue;
      },
      set(val) {
        this.$emit("update:modelValue", val);
        this.$emit("change", val);
      }
    },
    heightStyleName() {
      return {
        height: this.setPx(this.height)
      };
    },
    widthStyleName() {
      return {
        width: this.setPx(this.width)
      };
    },
    msgActive() {
      return !this.validatenull(this.msg.replace(/[\r\n]/g, ""));
    }
  },
  methods: {
    /**
     * 设置px像素
     */
    setPx(val, defval = "") {
      if (this.validatenull(val)) val = defval;
      if (this.validatenull(val)) return "";
      val = val + "";
      if (val.indexOf("%") === -1) {
        val = val + "px";
      }
      return val;
    },
    validatenull(val) {
      if (val instanceof Date || typeof val === "boolean" || typeof val === "number") return false;
      if (val instanceof Array) {
        if (val.length === 0) return true;
      } else if (val instanceof Object) {
        for (let o in val) {
          return false;
        }
        return true;
      } else {
        if (val === "null" || val == null || val === "undefined" || val === undefined || val === "") {
          return true;
        }
        return false;
      }
      return false;
    },
    handleUpload(type) {
      this.upload.type = type;
      this.upload.src = "";
      if (type === "img") {
        this.upload.title = "图片上传";
      } else if (type === "video") {
        this.upload.title = "视频上传";
      } else if (type === "file") {
        this.upload.title = "文件上传";
      }
      this.upload.box = true;
    },
    handleClose(done) {
      this.imgSrc = undefined;
      this.videoSrc = undefined;
      this.audioSrc = undefined;
      done();
    },
    addKey() {
      if (this.keys !== "") {
        this.$emit("keyadd", this.keys);
        this.keys = "";
      }
      this.visible = false;
    },
    sendKey(key) {
      this.$emit("keysend", key);
    },
    //mine为'我'的对话
    //text为内容
    pushMsg(params = {}) {
      const mine = params.mine === true ? true : false;
      const text = params.text || {};
      const date = params.date;
      const textObj = {
        ...params,
        date: date || dayjs().format("YYYY-MM-DD HH:mm:ss"),
        text: (() => {
          if (typeof text != "object") {
            return {
              text: text
            };
          }
          return text;
        })(),
        mine: mine,
        img: mine ? this.config.myImg : this.config.img,
        name: mine ? this.config.myName : this.config.name,
        msgType: params.msgType
      };
      this.list.push(textObj);
      setTimeout(() => {
        this.setScroll();
      }, 50);
    },
    setScroll(count) {
      //滚动条一直处于下方
      this.$nextTick(() => {
        this.$refs.main.scrollTop = count || this.$refs.main.scrollHeight;
      });
    },
    //用户主动发送
    handleSend() {
      if (this.msgActive) {
        this.$emit("submit");
      }
    },
    //选择列表
    handleItemMsg(item) {
      this.$emit("submit", item.ask);
    },
    //处理排版
    handleDetail(html = "") {
      let result = html;
      setTimeout(() => {
        const list = this.$refs.content || [];
        list.forEach(ele => {
          for (let i = 0; i < ele.children.length; i++) {
            const child = ele.children[i];
            if (child.getAttribute("data-flag") != 0) {
              child.setAttribute("data-flag", 0);
              child.onclick = () => {
                this.handleEvent(child.dataset);
              };
              if (child.tagName === "IMG") {
                child.className = "web__msg--img";
                child.src = child.getAttribute("data-src");
              } else if (child.tagName === "VIDEO") {
                child.className = "web__msg--video";
                child.src = child.getAttribute("data-src");
              } else if (child.tagName === "AUDIO") {
                child.className = "web__msg--audio";
                child.controls = "controls";
                child.src = child.getAttribute("data-src");
              } else if (child.tagName === "FILE") {
                child.className = "web__msg--file";
                child.innerHTML = `<h2>File</h2><span>${child.getAttribute("data-name")}</span>`;
              } else if (child.tagName === "MAP") {
                child.className = "web__msg--file web__msg--map";
                child.innerHTML = `<h2>Map</h2><span>${child.getAttribute("data-longitude")} , ${child.getAttribute("data-latitude")}<br />${child.getAttribute("data-address")}</span>`;
              }
              this.setScroll();
            }
          }
        });
      }, 0);
      return result;
    },
    getDetail(params = {}) {
      const { type, src, name, longitude, latitude, address } = params;
      if (type === "img") {
        return `<img data-type="IMG" data-src="${src}"  />`;
      } else if (type === "video") {
        return `<video data-type="VIDEO"  data-src="${src}"></video>`;
      } else if (type === "audio") {
        return `<audio data-type="AUDIO"  data-src="${src}"></audio>`;
      } else if (type === "file") {
        return `<file data-type="FILE" data-name="${name}" data-src="${src}"></file>`;
      } else if (type === "map") {
        return `<map data-type="MAP" data-src="${src}" data-address="${address} "data-latitude="${latitude}" data-longitude="${longitude}"></map>`;
      }
    },
    //处理事件
    handleEvent(params) {
      const callback = () => {
        if (params.type === "IMG") {
          this.imgSrc = params.src;
          this.show = true;
        } else if (params.type === "VIDEO") {
          this.videoSrc = params.src;
          this.show = true;
        } else if (params.type === "AUDIO") {
          this.audioSrc = params.src;
          this.show = true;
        } else if (params.type === "FILE") {
          window.open(params.src);
        }
      };
      if (typeof this.beforeOpen === "function") {
        this.beforeOpen(params, callback);
      } else {
        callback();
      }
    },
    rootSendMsg(msg, msgType, msgParams) {
      this.pushMsg({
        text: msg,
        msgType: msgType,
        ...msgParams
      });
    }
  }
});
</script>
<style scoped lang="scss">
@import "./chat.scss";
</style>
